<?php

namespace App\Http\Controllers\Base;

use App\Http\Controllers\Controller;
use Illuminate\Support\Facades\DB;
use App\Models\Storage\Goods;
use App\Jobs\SendAntiCode;

class TestController extends Controller
{
    private $txtMap = [
        'MasterBrand' => 'brand',
        'MasterCompany' => 'company',
        'MasterCustomer' => 'customer',
        'MasterDeliverAddress' => 'deliver_address',
        'MasterProdflg' => 'prod_flg',
        'MasterProduct' => 'product',
        'MasterReason' => 'reason',
        'MasterRejectedReason' => 'rejected_reason',
        'MasterSeries' => 'series',
        'MasterVendor' => 'vendor',
        'AdjOutDirt' => 'adj_out_dirt',
        'ASN' => 'asn',
        'MoveInDirt' => 'move_in_dirt',
        'MoveOutDirt' => 'move_out_dirt',
        'OrdOutDirt' => 'ord_out_dirt',
        'Pre-picking' => 'pre_picking',
        'ProdImp' => 'prod_imp',
        'RetInDirt' => 'ret_in_dirt',
    ];

    private $masterMap = [
        'brand' => 'BRANDCD',
        'company' => 'CompanyCd',
        'customer' => 'CUSTOMERCD',
        'deliver_address' => 'DeliverAddCD',
        'prod_flg' => 'PRODFLG',
        'product' => 'NewPRODUCTCD',
        'reason' => 'ReasonCd',
        'rejected_reason' => 'RejectedReasonCd',
        'series' => 'SERIESCD',
        'vendor' => 'VendorCode',
    ];

    private $okMap = [];
    private $path = '';

    public function __construct()
    {
        $this->path = storage_path() . DIRECTORY_SEPARATOR . 'uploads' . DIRECTORY_SEPARATOR . 'IN';
        // 禁用日志记录
        DB::connection()->disableQueryLog();
    }

    // 解析txt文件,返回一个数组
    private function parseOk($oks)
    {
        $result = [];
        foreach ($oks as $ok) {
            $filePath = $this->path . DIRECTORY_SEPARATOR . $ok;
            $dom = $this->checkBOM(file_get_contents($filePath));
            $res = explode(PHP_EOL, $dom);
            foreach ($res as $item) {
                $fields = explode("\x08", $item);
                $result[$fields[0]] = ['name' => $fields[0], 'size' => $fields[1], 'okFile' => $ok, 'time' => 0, 'count' => 0];
            }
        }

        $this->okMap = $result;
        $result = null;
    }

    private function parseTXT($txts)
    {
        DB::beginTransaction();
        try {
            foreach ($txts as $txt) {
                $start = microtime(true);
            // 验证文件
                $filePath = $this->path . DIRECTORY_SEPARATOR . $txt;
                if (!array_key_exists($txt, $this->okMap) || filesize($filePath) != $this->okMap[$txt]['size']) {
                    continue;
                }

            // 逐行读取
                $line = '';
                $count = 0;
                $keys = [];

                $fp = fopen($filePath, 'r');
                clearstatcache(true, $filePath);
            // 获取数据数组keys
                $line = $this->checkBOM(stream_get_line($fp, 8192, PHP_EOL));
                $fields = explode("\x08", $line);
                foreach ($fields as $key => $value) {
                    $keys[] = trim($value);
                }

            //获取values并处理
                while (!feof($fp)) {
                    $values = [];
                    $line = $this->checkBOM(stream_get_line($fp, 8192, PHP_EOL));
                    $fields = explode("\x08", $line);
                    foreach ($fields as $k => $v) {
                        if (trim($v) !== 0 && trim($v) !== '0' && empty(trim($v))) {
                            $v = null;
                        } else {
                            $v = trim($v);
                        }
                        $values[] = $v;
                    }
                    $item = array_combine($keys, $values);
                // 插入数据库
                    $this->insertToDB($txt, $item);
                    $this->okMap[$txt]['count']++;
                }
                fclose($fp);
                $this->okMap[$txt]['time'] = microtime(true) - $start;
            }
        } catch (\Exception $e) {
            DB::rollBack();
            return $e->getMessage();
        }
        DB::commit();
        return false;
    }

    private function insertToDB($name, $item)
    {
        foreach ($this->txtMap as $prefix => $tableName) {
            if (preg_match('/^' . $prefix . '[0-9]*.txt$/', $name)) {
                $item['created_at'] = date('Y-m-d H:i:s');
                if (in_array($tableName, array_keys($this->masterMap))) {
                    $record = DB::table($tableName)->where($this->masterMap[$tableName], $item[$this->masterMap[$tableName]])->first();
                    if ($record) {
                        DB::table($tableName)->where($this->masterMap[$tableName], $item[$this->masterMap[$tableName]])->update($item);
                    } else {
                        DB::table($tableName)->insert($item);
                    }
                } else {
                    DB::table($tableName)->insert($item);
                }
            }
        }
    }

    //过滤BOM
    private function checkBOM($contents)
    {
        $charset[1] = substr($contents, 0, 1);
        $charset[2] = substr($contents, 1, 1);
        $charset[3] = substr($contents, 2, 1);
        if (ord($charset[1]) == 239 && ord($charset[2]) == 187 && ord($charset[3]) == 191) {
            $rest = substr($contents, 3);
            return $rest;
        }
        return $contents;
    }

    // 入口
    public function scanForTXT()
    {
        set_time_limit(0);
        $start = microtime(true);

        if (!is_dir($this->path)) return '目录错误';
        $files = array_filter(scandir($this->path), function ($filename) {
            return is_file($this->path . DIRECTORY_SEPARATOR . $filename);
        });

        $oks = array_filter($files, function ($filename) {
            return preg_match('/[A-Za-z0-9\-]*.ok$/', $filename);
        });
        $txts = array_filter($files, function ($filename) {
            return preg_match('/[A-Za-z0-9\-]*.txt$/', $filename);
        });

        // 分析OK文件
        $this->parseOk($oks);
        if (empty($this->okMap)) return false;
        $okTime = microtime(true) - $start;
        // 处理TXT文件
        $res = $this->parseTXT($txts);
        if ($res) {
            return "发生错误，错误信息：" . $res;
        }
         // 删除和备份文件
        $path = storage_path() . DIRECTORY_SEPARATOR . 'uploads' . DIRECTORY_SEPARATOR . 'backup' . DIRECTORY_SEPARATOR . date('Ymd');
        if (!is_dir($path)) mkdir($path);
        $msg = '共处理' . count($txts) . '个文件<br>';
        foreach ($this->okMap as $value) {
            if (!rename($this->path . DIRECTORY_SEPARATOR . $value['name'], $path . DIRECTORY_SEPARATOR . $value['name'])) {
                $msg .= '文件' . $value['name'] . '备份失败<br>';
            }
            if (file_exists($this->path . DIRECTORY_SEPARATOR . $value['okFile'])) {
                if (!rename($this->path . DIRECTORY_SEPARATOR . $value['okFile'], $path . DIRECTORY_SEPARATOR . $value['okFile'])) {
                    $msg .= '文件' . $value['okFile'] . '备份失败<br>';
                }
            }
            $msg .= '文件' . $value['name'] . '更新了' . $value['count'] . '条数据，耗时' . $value['time'] . '秒<br>';
        }

        $msg .= '总耗时' . (microtime(true) - $start) . '秒';
        return $msg;
    }

    public function rec()
    {
        SendAntiCode::dispatch();
        // set_time_limit(0);
        // $map = [
        //     'adj_out_dirt' => ['matnr' => 'NewProductCd'],
        //     'ord_out_dirt' => ['matnr' => 'NewProductCd'],
        //     'move_out_dirt' => ['matnr' => 'NewProductCD'],
        // ];
        // $ensures = DB::table('ord_out_ensure')->get();
        $count = $fail = $success = 0;
        // foreach ($ensures as $ensure) {
        //     $count++;
        //     foreach ($map as $type => $value) {
        //         $query = [
        //             ['OutStcNo', '=', $ensure->VBELN],
        //             [$value['matnr'], '=', $ensure->MATNR],
        //         ];
        //         $order = DB::table($type)->where($query)->first();
        //         if (isset($order->id)) {
        //             if (DB::table($type.'_tag')->where('related_id', $order->id)->update(['status'=> '已回传'])) {
        //                 $success++;
        //             } else {
        //                 $fail++;
        //             }
        //         }
        //     }
        // }

        return '成功'.$success.'  失败'.$fail;

    }
}